package cn.db101.api.complex.utils

import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.core.JsonProcessingException
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.SerializationFeature
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer
import java.lang.RuntimeException
import java.io.IOException
import java.io.InputStream
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import java.util.HashMap

object JsonUtils {

    var MAPPER: ObjectMapper? = null

    init {
        MAPPER = ObjectMapper()
        MAPPER!!.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
        MAPPER!!.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
        MAPPER!!.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING)
        MAPPER!!.setSerializationInclusion(JsonInclude.Include.NON_NULL)
        MAPPER!!.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING)
        MAPPER!!.enable(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT)

        var javaTimeModule = JavaTimeModule();

        javaTimeModule.addSerializer(LocalDateTime::class.java, LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        javaTimeModule.addSerializer(LocalDate::class.java, LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));

        javaTimeModule.addDeserializer(LocalDateTime::class.java, LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));

        javaTimeModule.addDeserializer(LocalDate::class.java, LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));

        MAPPER!!.registerModule(javaTimeModule);

    }

    /**
     * java对象转换成json
     */
    fun <T> toJson(pojo: T): String {
        val result: String
        result = try {
            MAPPER!!.writeValueAsString(pojo)
        } catch (e: JsonProcessingException) {
            throw RuntimeException("json转换异常", e)
        }
        return result
    }

    /**
     * java对象转换成json
     */
    fun <T> toJson(pojos: List<T>?): String {
        val result: String
        result = try {
            MAPPER!!.writeValueAsString(pojos)
        } catch (e: JsonProcessingException) {
            throw RuntimeException("json转换异常", e)
        }
        return result
    }

    /**
     * java对象转换成json
     */
    fun <T> toObject(`is`: InputStream?, clazz: Class<T>?): T {
        val result: T
        result = try {
            MAPPER!!.readValue(`is`, clazz)
        } catch (e: JsonProcessingException) {
            throw RuntimeException("json转换异常", e)
        } catch (e: IOException) {
            throw RuntimeException("json转换异常", e)
        }
        return result
    }


    fun<T> toList(json: String?, valueType: Class<T>?): T {

        val result: T
        result = try {
            MAPPER!!.readValue(json, MAPPER!!.typeFactory.constructParametricType(List::class.java, valueType))
        } catch (e: JsonProcessingException) {
            throw RuntimeException("json转换异常", e)
        } catch (e: IOException) {
            throw RuntimeException("json转换异常", e)
        }
        return result

    }

    /**
     * java对象转换成json
     */
    fun <T> toObject(b: ByteArray?, clazz: Class<T>?): T {
        val result: T
        result = try {
            MAPPER!!.readValue(b, clazz)
        } catch (e: JsonProcessingException) {
            throw RuntimeException("json转换异常", e)
        } catch (e: IOException) {
            throw RuntimeException("json转换异常", e)
        }
        return result
    }

    fun <T> toMap(pojo: T): Map<String, Any> {
        var result: Map<String, Any>
        result = try {
            val str = MAPPER!!.writeValueAsString(pojo)
            MAPPER!!.readValue(str, HashMap<String, Any>().javaClass)
        } catch (e: JsonProcessingException) {
            throw RuntimeException("json转换异常", e)
        } catch (e: IOException) {
            throw RuntimeException("json转换异常", e)
        }

        return result
    }

    /**
     * json转换成Java对象
     */
    fun <T> fromJson(json: String?, valueType: Class<T>?): T {
        val t: T
        t = try {
            MAPPER!!.readValue(json, valueType)
        } catch (e: IOException) {
            throw RuntimeException("json转换异常", e)
        }
        return t
    }

    /**
     * json转换成Java对象
     */
    fun <T> fromJson(json: InputStream?, valueType: Class<T>?): T {
        val t: T
        t = try {
            MAPPER!!.readValue(json, valueType)
        } catch (e: IOException) {
            throw RuntimeException("json转换异常", e)
        }
        return t
    }
}
